home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-27 | 24.5 KB | 612 lines | [TEXT/ROSA] |
- Common Lisp the Language, 2nd Edition
- -------------------------------------------------------------------------------
-
- 21. Streams
-
- Streams are objects that serve as sources or sinks of data. Character streams
- produce or absorb characters; binary streams produce or absorb integers. The
- normal action of a Common Lisp system is to read characters from a character
- input stream, parse the characters as representations of Common Lisp data
- objects, evaluate each object (as a form) as it is read, and print
- representations of the results of evaluation to an output character stream.
-
- Typically streams are connected to files or to an interactive terminal.
- Streams, being Lisp objects, serve as the ambassadors of external devices by
- which input/output is accomplished.
-
- A stream, whether a character stream or a binary stream, may be input-only,
- output-only, or bidirectional. What operations may be performed on a stream
- depends on which of the six types of stream it is.
-
- -------------------------------------------------------------------------------
-
- * Standard Streams
- * Creating New Streams
- * Operations on Streams
-
- -------------------------------------------------------------------------------
-
- 21.1. Standard Streams
-
- There are several variables whose values are streams used by many functions in
- the Lisp system. These variables and their uses are listed here. By convention,
- variables that are expected to hold a stream capable of input have names ending
- with -input, and variables that are expected to hold a stream capable of output
- have names ending with -output. Variables expected to hold a bidirectional
- stream have names ending with -io.
-
- [Variable]
- *standard-input*
-
- In the normal Lisp top-level loop, input is read from *standard-input* (that
- is, whatever stream is the value of the global variable *standard-input*). Many
- input functions, including read and read-char, take a stream argument that
- defaults to *standard-input*.
-
- [Variable]
- *standard-output*
-
- In the normal Lisp top-level loop, output is sent to *standard-output* (that
- is, whatever stream is the value of the global variable *standard-output*).
- Many output functions, including print and write-char, take a stream argument
- that defaults to *standard-output*.
-
- [Variable]
- *error-output*
-
- The value of *error-output* is a stream to which error messages should be sent.
- Normally this is the same as *standard-output*, but *standard-output* might be
- bound to a file and *error-output* left going to the terminal or to a separate
- file of error messages.
-
- [Variable]
- *query-io*
-
- The value of *query-io* is a stream to be used when asking questions of the
- user. The question should be output to this stream, and the answer read from
- it. When the normal input to a program may be coming from a file, questions
- such as ``Do you really want to delete all of the files in your directory?''
- should nevertheless be sent directly to the user; and the answer should come
- from the user, not from the data file. For such purposes *query-io* should be
- used instead of *standard-input* and *standard-output*. *query-io* is used by
- such functions as yes-or-no-p.
-
- [Variable]
- *debug-io*
-
- The value of *debug-io* is a stream to be used for interactive debugging
- purposes. This is often the same as the value of *query-io*, but need not be.
-
- [Variable]
- *terminal-io*
-
- The value of *terminal-io* is ordinarily the stream that connects to the user's
- console. Typically, writing to this stream would cause the output to appear on
- a display screen, for example, and reading from the stream would accept input
- from a keyboard.
-
- It is intended that standard input functions such as read and read-char, when
- used with this stream, would cause ``echoing'' of the input into the output
- side of the stream. (The means by which this is accomplished are of course
- highly implementation-dependent.)
-
- [Variable]
- *trace-output*
-
- The value of *trace-output* is the stream on which the trace function prints
- its output.
-
- The variables *standard-input*, *standard-output*, *error-output*,
- *trace-output*, *query-io*, and *debug-io* are initially bound to synonym
- streams that pass all operations on to the stream that is the value of
- *terminal-io*. (See make-synonym-stream.) Thus any operations performed on
- those streams will go to the terminal.
-
- [change_begin]
- X3J13 voted in January 1989 (STANDARD-INPUT-INITIAL-BINDING) to replace the
- requirements of the preceding paragraph with the following new requirements:
-
- The seven standard stream variables, *standard-input*, *standard-output*,
- *query-io*, *debug-io*, *terminal-io*, *error-output*, and *trace-output*, are
- initially bound to open streams. (These will be called the standard initial
- streams.)
-
- The streams that are the initial values of *standard-input*, *query-io*,
- *debug-io*, and *terminal-io* must support input.
-
- The streams that are the initial values of *standard-output*, *error-output*,
- *trace-output*, *query-io*, *debug-io*, and *terminal-io* must support output.
-
- None of the standard initial streams (including the one to which *terminal-io*
- is initially bound) may be a synonym, either directly or indirectly, for any of
- the standard stream variables except *terminal-io*. For example, the initial
- value of *trace-output* may be a synonym stream for *terminal-io* but not a
- synonym stream for *standard-output* or *query-io*. (These are examples of
- direct synonyms.) As another example, *query-io* may be a two-way stream or
- echo stream whose input component is a synonym for *terminal-io*, but its input
- component may not be a synonym for *standard-input* or *debug-io*. (These are
- examples of indirect synonyms.)
-
- Any or all of the standard initial streams may be direct or indirect synonyms
- for one or more common implementation-dependent streams. For example, the
- standard initial streams might all be synonym streams (or two-way or echo
- streams whose components are synonym streams) to a pair of hidden terminal
- input and output streams maintained by the implementation.
-
- Part of the intent of these rules is to ensure that it is always safe to bind
- any standard stream variable to the value of any other standard stream variable
- (that is, unworkable circularities are avoided) without unduly restricting
- implementation flexibility.
- [change_end]
-
- No user program should ever change the value of *terminal-io*. A program that
- wants (for example) to divert output to a file should do so by binding the
- value of *standard-output*; that way error messages sent to *error-output* can
- still get to the user by going through *terminal-io*, which is usually what is
- desired.
-
- -------------------------------------------------------------------------------
-
- 21.2. Creating New Streams
-
- Perhaps the most important constructs for creating new streams are those that
- open files; see with-open-file and open. The following functions construct
- streams without reference to a file system.
-
- [Function]
- make-synonym-stream symbol
-
- make-synonym-stream creates and returns a synonym stream. Any operations on the
- new stream will be performed on the stream that is then the value of the
- dynamic variable named by the symbol. If the value of the variable should
- change or be bound, then the synonym stream will operate on the new stream.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-synonym-stream is always a stream of type synonym-stream. Note that the
- type of a synonym stream is always synonym-stream, regardless of the type of
- the stream for which it is a synonym.
- [change_end]
-
- [Function]
- make-broadcast-stream &rest streams
-
- This returns a stream that works only in the output direction. Any output sent
- to this stream will be sent to all of the streams given. The set of operations
- that may be performed on the new stream is the intersection of those for the
- given streams. The results returned by a stream operation are the values
- resulting from performing the operation on the last stream in streams; the
- results of performing the operation on all preceding streams are discarded. If
- no streams are given as arguments, then the result is a ``bit sink''; all
- output to the resulting stream is discarded.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-broadcast-stream is always a stream of type broadcast-stream.
- [change_end]
-
- [Function]
- make-concatenated-stream &rest streams
-
- This returns a stream that works only in the input direction. Input is taken
- from the first of the streams until it reaches end-of-file; then that stream is
- discarded, and input is taken from the next of the streams, and so on. If no
- arguments are given, the result is a stream with no content; any input attempt
- will result in end-of-file.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-concatenated-stream is always a stream of type concatenated-stream.
- [change_end]
-
- [Function]
- make-two-way-stream input-stream output-stream
-
- This returns a bidirectional stream that gets its input from input-stream and
- sends its output to output-stream.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-two-way-stream is always a stream of type two-way-stream.
- [change_end]
-
- [Function]
- make-echo-stream input-stream output-stream
-
- This returns a bidirectional stream that gets its input from input-stream and
- sends its output to output-stream. In addition, all input taken from
- input-stream is echoed to output-stream.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-echo-stream is always a stream of type echo-stream.
-
- X3J13 voted in January 1989 (PEEK-CHAR-READ-CHAR-ECHO) to clarify the
- interaction of read-char, unread-char, and peek-char with echo streams. (See
- the descriptions of those functions for details.)
-
- X3J13 explicitly noted that the bidirectional streams that are the initial
- values of *query-io*, *debug-io*, and *terminal-io*, even though they may have
- some echoing behavior, conceptually are not necessarily the products of calls
- to make-echo-stream and therefore are not subject to the new rules about
- echoing on echo streams. Instead, these initial interactive streams may have
- implementation-dependent echoing behavior.
- [change_end]
-
- [Function]
- make-string-input-stream string &optional start end
-
- This returns an input stream. The input stream will supply, in order, the
- characters in the substring of string delimited by start and end; after the
- last character has been supplied, the stream will then be at end-of-file.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-string-input-stream is always a stream of type string-stream.
- [change_end]
-
- [old_change_begin]
-
- [Function]
- make-string-output-stream
-
- This returns an output stream that will accumulate all output given it for the
- benefit of the function get-output-stream-string.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to let
- make-string-output-stream take an :element-type argument.
-
- [Function]
- make-string-output-stream &key :element-type
-
- This returns an output stream that will accumulate all output given it for the
- benefit of the function get-output-stream-string.
-
- The :element-type argument specifies what characters must be accepted by the
- created stream. If the :element-type argument is omitted, the created stream
- must accept all characters.
-
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- make-string-output-stream is always a stream of type string-stream.
- [change_end]
-
- [Function]
- get-output-stream-string string-output-stream
-
- Given a stream produced by make-string-output-stream, this returns a string
- containing all the characters output to the stream so far. The stream is then
- reset; thus each call to get-output-stream-string gets only the characters
- since the last such call (or the creation of the stream, if no such previous
- call has been made).
-
- [Macro]
- with-open-stream (var stream) {declaration}* {form}*
-
- The form stream is evaluated and must produce a stream. The variable var is
- bound with the stream as its value, and then the forms of the body are executed
- as an implicit progn; the results of evaluating the last form are returned as
- the value of the with-open-stream form. The stream is automatically closed on
- exit from the with-open-stream form, no matter whether the exit is normal or
- abnormal; see close. The stream should be regarded as having dynamic extent.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the stream
- created by with-open-stream is always of type file-stream.
- [change_end]
-
- [Macro]
-
- with-input-from-string (var string keyword {value}*)
- {declaration}* {form}*
-
- The body is executed as an implicit progn with the variable var bound to a
- character input stream that supplies successive characters from the value of
- the form string. with-input-from-string returns the results from the last form
- of the body.
-
- The input stream is automatically closed on exit from the
- with-input-from-string form, no matter whether the exit is normal or abnormal.
- The stream should be regarded as having dynamic extent.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the stream
- created by with-input-from-string is always of type string-stream.
- [change_end]
-
- The following keyword options may be used:
-
- :index
- The form after the :index keyword should be a place acceptable
- to setf. If the with-input-from-string form is exited normally,
- then the place will have stored into it the index into the
- string indicating the first character not read (the length of
- the string if all characters were used). The place is not
- updated as reading progresses, but only at the end of the
- operation.
-
- :start
- The :start keyword takes an argument indicating, in the manner
- usual for sequence functions, the beginning of a substring of
- string to be used.
-
- :end
- The :end keyword takes an argument indicating, in the manner
- usual for sequence functions, the end of a substring of string
- to be used.
-
- Here is an example of the use of with-input-from-string:
-
- (with-input-from-string (s "Animal Crackers" :index j :start 6)
- (read s)) => crackers
-
- As a side effect, the variable j is set to 15.
-
- The :start and :index keywords may both specify the same variable, which is a
- pointer within the string to be advanced, perhaps repeatedly by some containing
- loop.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [old_change_begin]
-
- [Macro]
-
- with-output-to-string (var [string]) {declaration}* {form}*
-
- The body is executed as an implicit progn with the variable var bound to a
- character output stream. All output to that stream is saved in a string. This
- may be done in one of two ways.
-
- If no string argument is provided, then the value of with-output-from-string is
- a string containing all the collected output.
-
- If string is specified, it must be a string with a fill pointer; the output is
- incrementally appended to the string, as if using vector-push-extend if the
- string is adjustable, and otherwise as if using vector-push. In this case
- with-output-to-string returns the results from the last form of the body.
-
- In either case, the output stream is automatically closed on exit from the
- with-output-from-string form, no matter whether the exit is normal or abnormal.
- The stream should be regarded as having dynamic extent.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to let
- with-output-to-string take an :element-type argument.
-
- [Macro]
-
- with-output-to-string (var [string [:element-type type]])
- {declaration}* {form}*
-
- One may specify nil instead of a string as the string and use the :element-type
- argument to specify what characters must be accepted by the created stream. If
- no string argument is provided, or if it is nil and no :element-type is
- specified, the created stream must accept all characters.
-
- X3J13 voted in October 1988 (WITH-OUTPUT-TO-STRING-APPEND-STYLE) to specify
- that if string is specified, it must be a string with a fill pointer; the
- output is incrementally appended to the string (as if by use of
- vector-push-extend).
-
- In this way output cannot be accidentally lost. This change makes
- with-output-to-string behave in the same way that format does when given a
- string as its first argument.
-
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the stream
- created by with-output-to-string is always of type string-stream.
-
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 21.3. Operations on Streams
-
- This section contains discussion of only those operations that are common to
- all streams. Input and output is rather complicated and is discussed separately
- in chapter 22. The interface between streams and the file system is discussed
- in chapter 23.
-
- [Function]
- streamp object
-
- streamp is true if its argument is a stream, and otherwise is false.
-
- (streamp x) == (typep x 'stream)
-
- [change_begin]
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
- streamp is unaffected by whether its argument, if a stream, is open or closed.
- In either case it returns true.
- [change_end]
-
- [change_begin]
-
- [Function]
- open-stream-p stream
-
- X3J13 voted in January 1989 (STREAM-ACCESS) to add the predicate
- open-stream-p. It is true if its argument (which must be a stream) is open, and
- otherwise is false.
-
- A stream is always created open; it remains open until closed with the close
- function. The macros with-open-stream, with-input-from-string,
- with-output-to-string, and with-open-file automatically close the created
- stream as control leaves their bodies, in effect imposing dynamic extent on the
- openness of the stream.
- [change_end]
-
- [Function]
- input-stream-p stream
-
- This predicate is true if its argument (which must be a stream) can handle
- input operations, and otherwise is false.
-
- [Function]
- output-stream-p stream
-
- This predicate is true if its argument (which must be a stream) can handle
- output operations, and otherwise is false.
-
- [Function]
- stream-element-type stream
-
- A type specifier is returned to indicate what objects may be read from or
- written to the argument stream, which must be a stream. Streams created by open
- will have an element type restricted to a subset of character or integer, but
- in principle a stream may conduct transactions using any Lisp objects.
-
- [Function]
- close stream &key :abort
-
- The argument must be a stream. The stream is closed. No further input/output
- operations may be performed on it. However, certain inquiry operations may
- still be performed, and it is permissible to close an already closed stream.
-
- [change_begin]
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) and revised the vote
- in March 1989 to specify that if close is called on an open stream, the stream
- is closed and t is returned; but if close is called on a closed stream, it
- succeeds without error and returns an unspecified value. (The rationale for not
- specifying the value returned for a closed stream is that in some
- implementations closing certain streams does not really have an effect on
- them-for example, closing the *terminal-io* stream might not ``really'' close
- it-and it is not desirable to force such implementations to keep otherwise
- unnecessary state. Portable programs will of course not rely on such behavior.)
-
- X3J13 also voted in January 1989 to specify exactly which inquiry functions may
- be applied to closed streams:
-
- streamp pathname-host namestring
- pathname pathname-device file-namestring
- truename pathname-directory directory-namestring
- merge-pathnames pathname-name host-namestring
- open pathname-type enough-namestring
- probe-file pathname-version directory
-
- See the individual descriptions of these functions for more information on how
- they operate on closed streams.
-
- X3J13 voted in January 1989 (CLOSE-CONSTRUCTED-STREAM) to clarify the effect
- of closing various kinds of streams. First some terminology:
-
- * A composite stream is one that was returned by a call to
- make-synonym-stream, make-broadcast-stream, make-concatenated-stream,
- make-two-way-stream, or make-echo-stream.
-
- * The constituents of a composite stream are the streams that were given as
- arguments to the function that constructed it or, in the case of
- make-synonym-stream, the stream that is the symbol-value of the symbol
- that was given as an argument. (The constituent of a synonym stream may
- therefore vary over time.)
-
- * A constructed stream is either a composite stream or one returned by a
- call to make-string-input-stream, make-string-output-stream,
- with-input-from-string, or with-output-to-string.
-
- The effect of applying close to a constructed stream is to close that stream
- only. No input/output operations are permitted on the constructed stream once
- it has been closed (though certain inquiry functions are still permitted, as
- described above).
-
- Closing a composite stream has no effect on its constituents; any constituents
- that are open remain open.
-
- If a stream created by make-string-output-stream is closed, the result of then
- applying get-output-stream-string to the stream is unspecified.
- [change_end]
-
- If the :abort parameter is not nil (it defaults to nil), it indicates an
- abnormal termination of the use of the stream. An attempt is made to clean up
- any side effects of having created the stream in the first place. For example,
- if the stream performs output to a file that was newly created when the stream
- was created, then if possible the file is deleted and any previously existing
- file is not superseded.
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to add the following accessor
- functions for obtaining information about streams.
-
- [Function]
- broadcast-stream-streams broadcast-stream
-
- The argument must be of type broadcast-stream. A list of the constituent output
- streams (whether open or not) is returned.
-
- [Function]
- concatenated-stream-streams concatenated-stream
-
- The argument must be of type concatenated-stream. A list of constituent streams
- (whether open or not) is returned. This list represents the ordered set of
- input streams from which the concatenated stream may yet read; the stream from
- which it is currently reading is first in the list. The list may be empty if no
- more streams remain to be read.
-
- [Function]
- echo-stream-input-stream echo-stream
- echo-stream-output-stream echo-stream
-
- The argument must be of type echo-stream. The function echo-stream-input-stream
- returns the constituent input stream; echo-stream-output-stream returns the
- constituent output stream.
-
- [Function]
- synonym-stream-symbol synonym-stream
-
- The argument must be of type synonym-stream. This function returns the symbol
- for whose value the synonym-stream is a synonym.
-
- [Function]
- two-way-stream-input-stream two-way-stream
- two-way-stream-output-stream two-way-stream
-
- The argument must be of type two-way-stream. The function
- two-way-stream-input-stream returns the constituent input stream;
- two-way-stream-output-stream returns the constituent output stream.
-
- [Function]
- interactive-stream-p stream
-
- X3J13 voted in June 1989 (STREAM-CAPABILITIES) to add the predicate
- interactive-stream-p, which returns t if the stream is interactive and
- otherwise returns nil. A type-error error is signalled if the argument is not
- of type stream.
-
- The precise meaning of interactive-stream-p is implementation-dependent and may
- depend on the underlying operating system. The intent is to distinguish between
- interactive and batch (background, command-file) operations. Some
- characteristics that might distinguish a stream as interactive:
-
- * The stream is connected to a person (or the equivalent) in such a way
- that the program can prompt for information and expect to receive input
- that might depend on the prompt.
-
- * The program is expected to prompt for input and to support ``normal input
- editing protocol'' for that operating environment.
-
- * A call to read-char might hang waiting for the user to type something
- rather than quickly returning a character or an end-of-file indication.
-
- The value of *terminal-io* might or might not be interactive.
-
- [Function]
- stream-external-format stream
-
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add the function
- stream-external-format, which returns a specifier for the
- implementation-recognized scheme used for representing characters in the
- argument stream. See the :external-format argument to open.
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
-
-